package org.zoomdev.zoom.common.caster;

import org.zoomdev.zoom.common.utils.Classes;
import org.zoomdev.zoom.common.utils.DateTimeUtils;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 在json转化的Map中，由于只存在简单类型
 * <p>
 * List/Map/String/Integer/Double/Boolean/Long
 * 并且，如果仅仅考虑有意义的转化 , 如 List 只能转为 List, Map 只能转为Bean,不存在 String与Map之间相互转化
 * 那么性能将大大提升
 */
public class FastToBeanCaster {
    private static final ConcurrentHashMap<Type, ValueCaster> CASTER_CACHE = new ConcurrentHashMap<>();

    static {
        // 初始化基础类型转换器
        // 字符串保持原样
        CASTER_CACHE.put(String.class, new BaseCaster(String.class) {
            @Override
            public Object to(Object src) {
                return src != null ? src.toString() : null;
            }
        });

        // 数值类型转换器
        CASTER_CACHE.put(int.class, new StringToNumberCaster(int.class));
        CASTER_CACHE.put(Integer.class, new StringToNumberCaster(Integer.class));
        CASTER_CACHE.put(long.class, new StringToNumberCaster(long.class));    // 添加long基本类型
        CASTER_CACHE.put(Long.class, new StringToNumberCaster(Long.class));      // 添加Long包装类型
        CASTER_CACHE.put(double.class, new StringToNumberCaster(double.class));
        CASTER_CACHE.put(Double.class, new StringToNumberCaster(Double.class));

        CASTER_CACHE.put(LocalDate.class, new StringToLocalDate());

        // 布尔类型转换器
        CASTER_CACHE.put(boolean.class, new BooleanCaster());
        CASTER_CACHE.put(Boolean.class, new BooleanCaster());

        // 注册基本类型
        CASTER_CACHE.put(int.class, new PrimitiveIntCaster());
        CASTER_CACHE.put(double.class, new PrimitiveDoubleCaster());
        CASTER_CACHE.put(boolean.class, new PrimitiveBooleanCaster());
        CASTER_CACHE.put(long.class, new PrimitiveLongCaster());
        CASTER_CACHE.put(float.class, new PrimitiveFloatCaster());
        CASTER_CACHE.put(short.class, new PrimitiveShortCaster());
        CASTER_CACHE.put(byte.class, new PrimitiveByteCaster());
        CASTER_CACHE.put(char.class, new PrimitiveCharCaster());
        CASTER_CACHE.put(BigDecimal.class, new BigDecimalCaster());

        CASTER_CACHE.put(Date.class, new DateCaster());
        CASTER_CACHE.put(Timestamp.class, new TimestampCaster());
        CASTER_CACHE.put(UUID.class, new String2UUID());
        CASTER_CACHE.put(byte[].class, new String2ByteArray());
        CASTER_CACHE.put(Enum.class, new EnumCaster()); // 注册通用枚举转换器

        CASTER_CACHE.put(LocalDateTime.class,new LocalDateTimeCaster());
    }


    static class LocalDateTimeCaster implements ValueCaster{

        @Override
        public Object to(Object src) {
            if(src == null){
                return null;
            }
            try {
                return LocalDateTime.parse((String) src, DateTimeUtils.DATE_TIME_FORMATTER);
            } catch (Exception e) {
                throw new CasterException("Failed to parse string to LocalDateTime: " + src, e);
            }
        }
    }

    static class BigDecimalCaster implements ValueCaster{

        @Override
        public Object to(Object src) {
            if(src == null){
                return null;
            }
            if(src instanceof BigDecimal){
                return src;
            }
            if(src instanceof String){
                return new BigDecimal((String)src);
            }
            if(src instanceof Integer){
                return new BigDecimal((Integer)src);
            }
            if(src instanceof Long){
                return new BigDecimal((Long)src);
            }

            throw new CasterException("Cannot cast "+src.getClass() + " to BigDecimal");
        }
    }

    static class TimestampCaster implements ValueCaster{

        @Override
        public Object to(Object src) {
            if(src == null){
                return null;
            }

            if(src instanceof Timestamp){
                return src;
            }

            if(src instanceof String){
                return Timestamp.valueOf(DateTimeUtils.parseStandardDateTime((String)src));
            }

            if(src instanceof Date){
                return new Timestamp(((Date)src).getTime());
            }

            throw new CasterException("Cannot cast "+src.getClass() + " to Timestamp");
        }
    }

    static class DateCaster implements ValueCaster{

        @Override
        public Object to(Object src) {
            if(src == null){
                return null;
            }
            if(src instanceof Date){
                return src;
            }

            if(src instanceof String){
                return BasicTypes.String2Date.STRING_2_DATE.to(src);
            }

            throw new CasterException("Cannot cast "+src.getClass() + " to Date");
        }
    }


    public static <T> T toBean(Map<String, Object> data, Type rawType, Type... typeArgs) {
        Type type = new ParameterizedTypeImpl(rawType, typeArgs, null);
        return toBean(data, type);
    }

    private static ValueCaster createCaster(Type t){

        if (t == Object.class) {
            return Caster.EQ_VALUE_CASTER;
        }

        if (t instanceof ParameterizedType) {
            ParameterizedType pType = (ParameterizedType) t;
            Type rawType = pType.getRawType();

            // 处理List<GenericType>
            if (rawType == List.class) {
                Type elementType = pType.getActualTypeArguments()[0];
                return new ListCaster(getCaster(elementType));
            }

            // 处理Map<GenericKey,GenericValue>
            if (rawType == Map.class) {
                Type[] typeArgs = pType.getActualTypeArguments();
                return new MapCaster(typeArgs[0], typeArgs[1]);
            }

            // 处理自定义泛型类
            if (rawType instanceof Class && ((Class<?>) rawType).getTypeParameters().length > 0) {
                return new BeanCaster(t);
            }
        }

        if (t instanceof Class) {
            Class<?> clazz = (Class<?>) t;

            // 处理数组类型
            if (clazz.isArray()) {
                Class<?> componentType = clazz.getComponentType();
                if (componentType.isPrimitive()) {
                    return new PrimitiveArrayCaster(componentType);
                }
                return new ListCaster(getCaster(componentType));
            }

            // 处理List类型
            if (List.class.isAssignableFrom(clazz)) {
                return new ListCaster(getCaster(Object.class));
            }

            // 处理基本类型
            if (clazz.isPrimitive()) {
                throw new IllegalStateException("All primitives should be pre-registered");
            }

            if (clazz.isEnum()) {
                return new EnumCaster((Class<? extends Enum>) clazz);
            }



            if(!Classes.isJavaClass(clazz) && !Classes.isSimple(clazz)){
                // 处理Bean类型
                return new FastMap2BeanCaster(clazz);
            }

        }
        throw new CasterException("不支持的类型:" + t);
    }

    // 修改后的getCaster方法
    public static ValueCaster getCaster(Type type) {
        ValueCaster caster = CASTER_CACHE.get(type);
        if(caster == null){
            caster = createCaster(type);
            CASTER_CACHE.putIfAbsent(type,caster);
        }
        return caster;
    }

    @SuppressWarnings("unchecked")
    public static <T> List<T> toBeanList(List<?> list, Class<T> type) {
        ValueCaster caster = getCaster(type);
        List<T> result = new ArrayList<>(list.size());
        for (Object item : list) {
            result.add((T) caster.to(item));
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public static <T> T toBean(Map<String, Object> data, Type type) {
        return (T) getCaster(type).to(data);
    }

    public static Object to(Object value, Type type) {
        return getCaster(type).to(value);
    }

    public static void register(Class<?> type, ValueCaster caster) {
        CASTER_CACHE.put(type, caster);
    }

    static class String2UUID implements ValueCaster {

        @Override
        public Object to(Object src) {
            if (src == null) return null;
            return UUID.fromString((String) src);
        }
    }

    static class String2ByteArray implements ValueCaster {

        @Override
        public Object to(Object src) {
            if (src == null) return null;
            return Base64.decodeFast((String) src);
        }
    }

    public static class ParameterizedTypeImpl implements ParameterizedType {
        private final Type rawType;
        private final Type[] typeArguments;
        private final Type ownerType;

        public ParameterizedTypeImpl(Type rawType, Type[] typeArguments, Type ownerType) {
            this.rawType = rawType;
            this.typeArguments = typeArguments;
            this.ownerType = ownerType;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return typeArguments;
        }

        @Override
        public Type getRawType() {
            return rawType;
        }

        @Override
        public Type getOwnerType() {
            return ownerType;
        }
    }

    public static class StringToLocalDate implements ValueCaster {
        @Override
        public Object to(Object src) {
            // 1. 参数校验
            if (src == null) {
                throw new IllegalArgumentException("输入参数不能为null");
            }

            if (!(src instanceof String)) {
                throw new IllegalArgumentException("输入参数必须是字符串类型");
            }

            String dateStr = (String) src;


            // 3. 执行转换
            try {
                return LocalDate.parse(dateStr, DateTimeUtils.DATE_FORMATTER);
            } catch (Exception e) {
                throw new CasterException(
                        String.format("无法将字符串'%s'转换为LocalDate，请确保格式为yyyy-MM-dd", dateStr),
                        e
                );
            }
        }
    }

    // 其他基本类型转换器实现类似...

    // 枚举类型转换器
    static class EnumCaster extends BaseCaster {
        private final Class<? extends Enum> enumType;

        EnumCaster() {
            this(null); // 用于泛型注册
        }

        EnumCaster(Class<? extends Enum> enumType) {
            super(enumType);
            this.enumType = enumType;
        }

        @Override
        public Object to(Object src) {
            if (src == null) return null;

            // 如果已明确指定枚举类型
            if (enumType != null) {
                return convertToEnum(src, enumType);
            }

            // 动态处理未绑定具体类型的转换（需在getCaster时指定类型）
            throw new CasterException("Enum type must be specified for conversion");
        }

        @SuppressWarnings("unchecked")
        private <E extends Enum<E>> E convertToEnum(Object value, Class<E> enumType) {
            try {
                if (value instanceof String) {
                    return Enum.valueOf(enumType, (String) value);
                }
                if (value instanceof Number) {
                    int ordinal = ((Number) value).intValue();
                    E[] constants = enumType.getEnumConstants();
                    if (ordinal < 0 || ordinal >= constants.length) {
                        throw new CasterException("Invalid ordinal for " + enumType + ": " + ordinal);
                    }
                    return constants[ordinal];
                }
                throw new CasterException("Unsupported conversion to enum from: " + value.getClass());
            } catch (IllegalArgumentException e) {
                throw new CasterException("Invalid enum value: " + value + " for " + enumType, e);
            }
        }
    }

    // 基本类型转换器基类
    private abstract static class PrimitiveCaster<T> implements ValueCaster {
        @Override
        public Object to(Object src) {
            if (src == null) {
                return defaultValue(); // 处理null值
            }
            return parse(src);
        }

        protected abstract T parse(Object value);

        protected Object defaultValue() {
            throw new IllegalArgumentException("Cannot convert null to primitive type");
        }
    }

    // int类型转换器
    static class PrimitiveIntCaster extends PrimitiveCaster<Integer> {
        @Override
        protected Integer parse(Object value) {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            }
            if (value instanceof String) {
                try {
                    return Integer.parseInt((String) value);
                } catch (NumberFormatException e) {
                    throw new CasterException(e);
                }

            }
            throw new IllegalArgumentException("Cannot convert to int: " + value.getClass());
        }

        @Override
        protected Object defaultValue() {
            return 0; // 默认值
        }
    }

    // double类型转换器
    static class PrimitiveDoubleCaster extends PrimitiveCaster<Double> {
        @Override
        protected Double parse(Object value) {
            if (value instanceof Number) {
                return ((Number) value).doubleValue();
            }
            if (value instanceof String) {
                return Double.parseDouble((String) value);
            }
            throw new IllegalArgumentException("Cannot convert to double: " + value.getClass());
        }

        @Override
        protected Object defaultValue() {
            return 0.0;
        }
    }

    //
//    // Bean转换器
    private static class BeanCaster implements ValueCaster {
        private final Type beanType;
        private final Map<String, Type> typeVariables; // 类型变量映射（如 T -> User）

        BeanCaster(Type beanType) {
            this.beanType = beanType;
            this.typeVariables = resolveTypeVariables(beanType);
        }

        @Override
        public Object to(Object src) {
            Map<?, ?> map = (Map<?, ?>) src;
            try {
                Class<?> clazz = getRawClass(beanType);
                Object instance = clazz.getDeclaredConstructor().newInstance();
                ValueCaster fieldCaster = null;
                for (Field field : clazz.getDeclaredFields()) {
                    Type fieldType = field.getGenericType();
                    Type resolvedType = resolveFieldType(fieldType); // 解析字段的实际类型
                    if(resolvedType instanceof ParameterizedType){
                       Class<?> rawClass = (Class<?>) ((ParameterizedType)resolvedType).getRawType();
                       if(Map.class.isAssignableFrom(rawClass)){
                           fieldCaster = Caster.EQ_VALUE_CASTER;
                       }
                    }
                    if(fieldCaster==null){
                        fieldCaster = getCaster(resolvedType);
                    }
                    Object value1 = map.get(field.getName());
                    if (value1 != null) {
                        Object value = fieldCaster.to(value1);
                        field.setAccessible(true);
                        field.set(instance, value);
                    }

                }
                return instance;
            } catch (Exception e) {
                throw new CasterException("Create bean failed: " + beanType, e);
            }
        }

        // 解析泛型参数（如 Response<User> 中的 User）
        private Map<String, Type> resolveTypeVariables(Type type) {
            Map<String, Type> typeMap = new HashMap<>();
            if (type instanceof ParameterizedType) {
                ParameterizedType pType = (ParameterizedType) type;
                Class<?> rawClass = (Class<?>) pType.getRawType();
                Type[] actualArgs = pType.getActualTypeArguments();
                TypeVariable<?>[] typeParams = rawClass.getTypeParameters();

                for (int i = 0; i < typeParams.length; i++) {
                    typeMap.put(typeParams[i].getName(), actualArgs[i]);
                }
            }
            return typeMap;
        }

        // 解析字段类型（替换类型变量）
        private Type resolveFieldType(Type fieldType) {
            if (fieldType instanceof TypeVariable) {
                String name = ((TypeVariable<?>) fieldType).getName();
                return typeVariables.getOrDefault(name, fieldType);
            } else if (fieldType instanceof ParameterizedType) {
                ParameterizedType pType = (ParameterizedType) fieldType;
                Type[] actualArgs = pType.getActualTypeArguments();
                Type[] resolvedArgs = new Type[actualArgs.length];
                for (int i = 0; i < actualArgs.length; i++) {
                    resolvedArgs[i] = resolveFieldType(actualArgs[i]);
                }
                return new ParameterizedTypeImpl(
                        pType.getRawType(),
                        resolvedArgs,
                        pType.getOwnerType()
                );
            }
            return fieldType;
        }

        private Class<?> getRawClass(Type type) {
            return type instanceof Class ? (Class<?>) type : (Class<?>) ((ParameterizedType) type).getRawType();
        }
    }

    // 基本类型数组转换器
    static class PrimitiveArrayCaster implements ValueCaster {
        private final Class<?> componentType;
        private final ValueCaster elementCaster;

        PrimitiveArrayCaster(Class<?> componentType) {
            this.componentType = componentType;
            this.elementCaster = CASTER_CACHE.get(componentType);
        }

        @Override
        public Object to(Object src) {
            List<?> list = (List<?>) src;
            Object array = Array.newInstance(componentType, list.size());

            for (int i = 0; i < list.size(); i++) {
                Object value = elementCaster.to(list.get(i));
                Array.set(array, i, value);
            }
            return array;
        }
    }

    // 基础类型直接转换


    // List转换器
    private static class ListCaster implements ValueCaster {

        private final ValueCaster elementCaster;

        ListCaster(ValueCaster elementCaster) {
            this.elementCaster = elementCaster;
        }

        @Override
        public Object to(Object src) {
            List<?> sourceList = (List<?>) src;
            List<Object> result = new ArrayList<>(sourceList.size());
            for (Object item : sourceList) {
                result.add(elementCaster.to(item));
            }
            return result;
        }
    }

    // 布尔类型转换器
    static class PrimitiveBooleanCaster extends PrimitiveCaster<Boolean> {
        @Override
        protected Boolean parse(Object value) {
            if (value instanceof Boolean) {
                return (Boolean) value;
            }
            if (value instanceof Number) {
                return ((Number) value).intValue() != 0;
            }
            if (value instanceof String) {
                String str = ((String) value).trim().toLowerCase();
                if ("true".equals(str) || "1".equals(str)) return true;
                if ("false".equals(str) || "0".equals(str)) return false;
            }
            throw new IllegalArgumentException("Cannot convert to boolean: " + value.getClass());
        }

        @Override
        protected Object defaultValue() {
            return false;
        }
    }

    // 长整型转换器
    static class PrimitiveLongCaster extends PrimitiveCaster<Long> {
        @Override
        protected Long parse(Object value) {
            if (value instanceof Number) {
                return ((Number) value).longValue();
            }
            if (value instanceof String) {
                try {
                    return Long.parseLong((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Invalid long format: " + value);
                }
            }
            throw new IllegalArgumentException("Cannot convert to long: " + value.getClass());
        }

        @Override
        protected Object defaultValue() {
            return 0L;
        }
    }

    // 单精度浮点型转换器
    static class PrimitiveFloatCaster extends PrimitiveCaster<Float> {
        @Override
        protected Float parse(Object value) {
            if (value instanceof Number) {
                return ((Number) value).floatValue();
            }
            if (value instanceof String) {
                try {
                    return Float.parseFloat((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Invalid float format: " + value);
                }
            }
            throw new IllegalArgumentException("Cannot convert to float: " + value.getClass());
        }

        @Override
        protected Object defaultValue() {
            return 0.0f;
        }
    }

    // 短整型转换器（带范围检查）
    static class PrimitiveShortCaster extends PrimitiveCaster<Short> {
        @Override
        protected Short parse(Object value) {
            long num;
            if (value instanceof Number) {
                num = ((Number) value).longValue();
            } else if (value instanceof String) {
                try {
                    num = Long.parseLong((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Invalid short format: " + value);
                }
            } else {
                throw new IllegalArgumentException("Cannot convert to short: " + value.getClass());
            }

            if (num < Short.MIN_VALUE || num > Short.MAX_VALUE) {
                throw new IllegalArgumentException("Value out of short range: " + num);
            }
            return (short) num;
        }

        @Override
        protected Object defaultValue() {
            return (short) 0;
        }
    }

    // 字节型转换器（带严格范围检查）
    static class PrimitiveByteCaster extends PrimitiveCaster<Byte> {
        @Override
        protected Byte parse(Object value) {
            long num;
            if (value instanceof Number) {
                num = ((Number) value).longValue();
            } else if (value instanceof String) {
                try {
                    num = Long.parseLong((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Invalid byte format: " + value);
                }
            } else {
                throw new IllegalArgumentException("Cannot convert to byte: " + value.getClass());
            }

            if (num < Byte.MIN_VALUE || num > Byte.MAX_VALUE) {
                throw new IllegalArgumentException("Value out of byte range: " + num);
            }
            return (byte) num;
        }

        @Override
        protected Object defaultValue() {
            return (byte) 0;
        }
    }

    // 字符型转换器（支持多种输入形式）
    static class PrimitiveCharCaster extends PrimitiveCaster<Character> {
        @Override
        protected Character parse(Object value) {
            if (value instanceof Character) {
                return (Character) value;
            }
            if (value instanceof Number) {
                int code = ((Number) value).intValue();
                if (code < Character.MIN_VALUE || code > Character.MAX_VALUE) {
                    throw new IllegalArgumentException("Invalid character code: " + code);
                }
                return (char) code;
            }
            if (value instanceof String) {
                String str = (String) value;
                if (str.length() == 1) {
                    return str.charAt(0);
                }
                throw new IllegalArgumentException("String must be exactly 1 character long");
            }
            throw new IllegalArgumentException("Cannot convert to char: " + value.getClass());
        }

        @Override
        protected Object defaultValue() {
            return '\u0000';
        }
    }

    // 新增Map泛型转换器
    private static class MapCaster implements ValueCaster {
        private final Type keyType;
        private final Type valueType;

        MapCaster(Type keyType, Type valueType) {
            this.keyType = keyType;
            this.valueType = valueType;
        }

        @Override
        public Object to(Object src) {
            Map<?, ?> sourceMap = (Map<?, ?>) src;
            Map<Object, Object> result = new HashMap<>();
            ValueCaster keyCaster = getCaster(keyType);
            ValueCaster valueCaster = getCaster(valueType);

            for (Map.Entry<?, ?> entry : sourceMap.entrySet()) {
                Object key = keyCaster.to(entry.getKey());
                Object value = valueCaster.to(entry.getValue());
                result.put(key, value);
            }
            return result;
        }
    }

    // 基础类型转换器体系
    static abstract class BaseCaster implements ValueCaster {
        protected final Class<?> targetType;

        BaseCaster(Class<?> targetType) {
            this.targetType = targetType;
        }

        protected Object handleNull() {
            if (targetType.isPrimitive()) {
                return getPrimitiveDefault(targetType);
            }
            return null;
        }

        private Object getPrimitiveDefault(Class<?> type) {
            if (type == int.class) return 0;
            if (type == long.class) return 0L;
            if (type == double.class) return 0.0;
            if (type == boolean.class) return false;
            // 其他基本类型...
            throw new IllegalArgumentException("Unsupported primitive type: " + type);
        }
    }


    // 字符串到数值类型转换器
    static class StringToNumberCaster extends BaseCaster {
        StringToNumberCaster(Class<?> targetType) {
            super(targetType);
        }

        @Override
        public Object to(Object src) {
            if (src == null) return handleNull();

            if (src instanceof Number) {
                return convertNumber((Number) src);
            }

            if (src instanceof String) {
                try {
                    String str = ((String) src).trim();
                    if (targetType == Integer.class || targetType == int.class) {
                        return Integer.parseInt(str);
                    }
                    if (targetType == Double.class || targetType == double.class) {
                        return Double.parseDouble(str);
                    }
                    if (targetType == Long.class || targetType == long.class) {
                        return Long.parseLong(str);
                    }
                } catch (NumberFormatException e) {
                    throw new CasterException("Invalid number format: " + src);
                }
            }
            throw new CasterException("Cannot convert " + src.getClass() + " to " + targetType);
        }

        private Number convertNumber(Number number) {
            if (targetType == Integer.class || targetType == int.class) {
                return number.intValue();
            }
            if (targetType == Double.class || targetType == double.class) {
                return number.doubleValue();
            }

            if (targetType == Long.class || targetType == long.class) {
                return number.longValue();
            }
            // 其他数值类型转换...
            throw new CasterException("Unsupported number conversion to " + targetType);
        }
    }

    // 布尔值转换器（支持多种输入类型）
    static class BooleanCaster extends BaseCaster {
        BooleanCaster() {
            super(boolean.class);
        }

        @Override
        public Object to(Object src) {
            if (src == null) return handleNull();

            if (src instanceof Boolean) {
                return src;
            }
            if (src instanceof Number) {
                return ((Number) src).intValue() != 0;
            }
            if (src instanceof String) {
                String str = ((String) src).trim().toLowerCase();
                if ("true".equals(str) || "1".equals(str)) return true;
                if ("false".equals(str) || "0".equals(str)) return false;
            }
            throw new CasterException("Cannot convert to boolean: " + src.getClass());
        }
    }
}
